grammar Test;

//prog 是文法的入口， 一个 prog 有一个或多个函数定义组成。
prog: funDecl+;

// 函数定义， 有函数名 ID、 参数列表和语句块构成。
funDecl  :ID '(' paramDeclList ')' block;

// 参数列表有 0 个或多个参数定义。
paramDeclList
    :   (paramDecl (',' paramDecl)*)?;

// 参数定义对应一个词法符号 ID
paramDecl
    :   ID
;

// 语句块由花括号和语句列表组成。
block
    :  '{' stmtList '}';

// 语句列表由 0 个或多个语句组成。
stmtList:stat*    ;


stat: ID '=' expr ';' #Assign //变量赋值语句
| 'print' '(' expr ')' ';' #printExpr   //输出语句
;

expr: expr op=('*'|'/') expr #MulDiv  //表达式可以是表达式之间乘除
  | expr op=('+'|'-') expr #AddSub  //表达式可以是表达式之间加减
  | NUM #NUM    //表达式可以是一个数字
  | ID #ID  //表达式可以是一个变脸
  | '(' expr ')' #parens    //表达式可以被括号括起来
  ;

MUL:'*';
DIV:'/';
ADD:'+';
SUB:'-';

ID: [a-zA-Z][a-zA-Z0-9]*; //变量可以是数字和字母，但必须以字母开头

//负数必须要用"()"括起来
NUM: [0-9]+   //正整数
  | '(' '-' [0-9]+ ')'  //负整数
| [0-9]+'.'[0-9]+   //正浮点数
| '(' '-' [0-9]+'.'[0-9]+ ')'   //负浮点数
;

WS: [ \t\r\n] -> skip;    //跳过空格、制表符、回车、换行
